package licode.unisop.single.user.infrastructure.repository.dao;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import licode.unisop.provider.conf.SiAssetState;
import licode.unisop.provider.info.UserGroupLookupIn;
import licode.unisop.provider.info.UserGroupQueryPageIn;
import licode.unisop.provider.info.UserGroupSaveIn;
import licode.unisop.provider.utils.StrUtil;
import licode.unisop.provider.vo.SiPageResult;
import licode.unisop.provider.vo.SiProps;
import licode.unisop.provider.vo.SiUserGroup;
import licode.unisop.single.user.application.entity.RealmAssetEntity;
import licode.unisop.single.user.application.gateway.RealmAssetDao;
import licode.unisop.single.user.infrastructure.assembler.UniUserSingleAssembler;
import licode.unisop.single.user.infrastructure.repository.mapper.RealmAssetMapper;
import licode.unisop.single.user.infrastructure.repository.po.RealmAssetPO;
import licode.unisop.single.user.infrastructure.utils.PageUtil;
import licode.unisop.types.util.IdGenUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * uni-user-single
 *
 * @author licode
 * @date 2016-04-11 10:58:29
 */
@Component
public class RealmAssetDaoImpl
        extends ServiceImpl<RealmAssetMapper, RealmAssetPO>
        implements RealmAssetDao {
    @Resource
    private UniUserSingleAssembler uniUserSingleAssembler;

    @Override
    public void add(RealmAssetEntity item) {
        super.save(uniUserSingleAssembler.fromRealmAssetEntity(item));
    }

    @Override
    public void update(RealmAssetEntity item) {
        super.updateById(uniUserSingleAssembler.fromRealmAssetEntity(item));
    }

    @Override
    public void removeWithId(Serializable id) {
        super.removeById(id);
    }

    @Override
    public RealmAssetEntity getWithId(Serializable id) {
        return uniUserSingleAssembler.fromRealmAsset(super.getById(id));
    }

    @Override
    public SiUserGroup lookupUserGroup(UserGroupLookupIn req) {
        RealmAssetPO realmAsset = super.lambdaQuery()
                .eq(RealmAssetPO::getOwnerId, req.getRealmId())
                .in(RealmAssetPO::getId, req.getGroupId())
                .one();
        return null == realmAsset ? null : convertToUserGroup(realmAsset);
    }

    @Override
    public void saveUserGroup(UserGroupSaveIn group) {
        RealmAssetPO assetPO = null;
        if (StrUtil.isNotBlank(group.getGroup().getId())) {
            assetPO = super.lambdaQuery()
                    .eq(RealmAssetPO::getOwnerId, group.getRealmId())
                    .eq(RealmAssetPO::getId, group.getGroup().getId())
                    .one();
        }

        if (null != assetPO) {
            SiUserGroup usrGroup = group.getGroup();
            String strProps = null == usrGroup.getProps() ? null : JSON.toJSONString(usrGroup.getProps());

            super.lambdaUpdate()
                    .set(null != usrGroup.getName(), RealmAssetPO::getName, usrGroup.getName())
                    .set(null != usrGroup.getLevel(), RealmAssetPO::getLevel, usrGroup.getLevel())
                    .set(null != usrGroup.getState(), RealmAssetPO::getState, usrGroup.getState())
                    .set(RealmAssetPO::getProps, strProps)
                    .set(RealmAssetPO::getUpdateTime, LocalDateTime.now())
                    .eq(RealmAssetPO::getOwnerId, group.getRealmId())
                    .eq(RealmAssetPO::getId, usrGroup.getId())
                    .update();
        } else {
            assetPO = new RealmAssetPO();
            assetPO.setId(IdGenUtil.buildUserGroupId());
            assetPO.setName(group.getGroup().getName());
            assetPO.setCode("");
            assetPO.setClassify("");
            assetPO.setLevel(group.getGroup().getLevel());
            assetPO.setOwnerId(group.getRealmId());
            assetPO.setParentId("");
            assetPO.setRootId("");
            assetPO.setState(group.getGroup().getState());
            assetPO.setSubType("");
            assetPO.setTerminalCode("");
            assetPO.setType("USER_GROUP");
            assetPO.setProps(group.getGroup().getProps());
            assetPO.setUpdateTime(LocalDateTime.now());
            assetPO.setCreateTime(LocalDateTime.now());
            super.save(assetPO);
        }
    }

    @Override
    public SiPageResult<SiUserGroup> findUserGroupPage(UserGroupQueryPageIn req) {
        Page<RealmAssetPO> page = new Page<>(req.getCurrent(), req.getPageSize());
        page = super.lambdaQuery()
                .like(StrUtil.isNotBlank(req.getName()), RealmAssetPO::getName, req.getName())
                .eq(RealmAssetPO::getOwnerId, req.getRealmId())
                .eq(null != req.getState() && req.getState() > -1,
                        RealmAssetPO::getState, req.getState())
                .ne(RealmAssetPO::getState, SiAssetState.AT_DELETED)
                .orderByDesc(RealmAssetPO::getCreateTime)
                .page(page);
        return PageUtil.convertPage(page, this::convertToUserGroup);
    }

    @Override
    public List<SiUserGroup> findUserGroupList(String realmId, List<String> ids) {
        List<RealmAssetPO> result = super.lambdaQuery()
                .eq(RealmAssetPO::getOwnerId, realmId)
                .in(RealmAssetPO::getId, ids)
                .orderByDesc(RealmAssetPO::getCreateTime)
                .list();

        return null == result ? null : convertToUserGroup(result);
    }

    public SiUserGroup convertToUserGroup(RealmAssetPO item) {
        SiUserGroup result = new SiUserGroup();

        result.setId(item.getId());
        result.setName(item.getName());
        result.setState(item.getState());
        result.setLevel(item.getLevel());
        result.setCode(item.getCode());
        if (null != item.getProps()) {
            result.setProps(SiProps.build(item.getProps()));
        }
        result.setCreateTime(item.getCreateTime());

        return result;
    }

    public List<SiUserGroup> convertToUserGroup(List<RealmAssetPO> plList) {
        List<SiUserGroup> targetPl = new ArrayList<>();

        plList.forEach(item -> targetPl.add(convertToUserGroup(item)));

        return targetPl;
    }
}
